//
//  WYLocationHelper.m
//  Boss
//
//  Created by admin on 2018/6/4.
//  Copyright © 2018年 admin. All rights reserved.
//

#import "WYLocationHelper.h"
static const double OBLATE = 1 / 298.257223563;
static const double POLAR_RADIUS = 6356752.3142;
static const double EQUATORIAL_RADIUS = 6378137;
@implementation WYLocationHelper
+(WYLocationBean *)generateRandomScopeLocation:(WYLocationBean *)oldLocation
{
    return [self computeLocation:oldLocation WithAngle:arc4random() % 360 WithDistance:arc4random() % 1500];
}
+(WYLocationBean *)computeLocation:(WYLocationBean *)oldLocation WithAngle:(double)angle WithDistance:(double)distance
{
    WYLocationBean *newLocation = [[WYLocationBean alloc]init];
    
    
    double alpha1 = [self rad:angle];
    double sinAlpha1 = sin(alpha1);
    double cosAlpha1 = cos(alpha1);
    
    double tanU1 = (1 - OBLATE) *tan([self rad:oldLocation.lat]);
    double cosU1 = 1 / sqrt(1 + tanU1 * tanU1);
    
    double sinU1 = tanU1 * cosU1;
    
    double sigma1 =atan2(tanU1, cosAlpha1);
    
    double sinAlpha = cosU1 * sinAlpha1;
    
    double cosSqAlpha = 1 - sinAlpha * sinAlpha;
    
    double uSq = cosSqAlpha * (EQUATORIAL_RADIUS * EQUATORIAL_RADIUS - POLAR_RADIUS * POLAR_RADIUS) / (POLAR_RADIUS * POLAR_RADIUS);
    
    double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
    
    double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
    
    double sigma = distance / (POLAR_RADIUS*A);
    
    double sigmaP = 2*M_PI;
    
    double cos2SigmaM=0;
    
    double sinSigma=0;
    
    double cosSigma=0;
    
    double deltaSigma=0;
    
    while (fabs(sigma-sigmaP) > (1e-12)) {
        cos2SigmaM =cos(2*sigma1 + sigma);
        sinSigma = sin(sigma);
        cosSigma = cos(sigma);
        deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
                                                 B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
        sigmaP = sigma;
        sigma = distance / (POLAR_RADIUS*A) + deltaSigma;
    }
    
    double tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
    double lat2 = atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
                             (1-OBLATE)*sqrt(sinAlpha*sinAlpha + tmp*tmp));
    double lambda = atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
    double C = OBLATE/16*cosSqAlpha*(4+OBLATE*(4-3*cosSqAlpha));
    double L = lambda - (1-C) * OBLATE * sinAlpha *
    (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
    
    //double revAz = atan2(sinAlpha, -tmp);
    
    newLocation.lat = [self deg:lat2];
    newLocation.lon = oldLocation.lon + [self deg:L];
    
    //newLocation.setLon(oldLocation.getLon()+(deg(L)));
    
    return newLocation;
}

+(double)rad:(double)d
{
    return d * M_PI / 180.0;
}

+(double)deg:(double)x
{
    return x * 180 / M_PI;
}
@end
